﻿using ezCloud.Api.Models;
using ezCloud.Data;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;

namespace ezCloud.Api.Common
{
    public class ReservationUtility
    {
        public static IEnumerable<DateTime> EachDay(IRange<DateTime> range)
        {
            for (var day = range.Start; day.Date <= range.End.Date; day = day.AddDays(1))
                yield return day;
        }

        public static IEnumerable<DateTime> EachDayWithTime(IRange<DateTime> range, Hotels hotel)
        {
            for (var day = range.Start; day <= range.End; day = day.AddDays(1))
                yield return day;
        }

        public static IEnumerable<DateTime> EachDayWithTimeZero(IRange<DateTime> range, Hotels currentHotel)
        {
            for (var day = range.Start.AddMinutes(currentHotel.TimeZoneOffset).Date; day <= range.End.AddMinutes(currentHotel.TimeZoneOffset).Date; day = day.AddDays(1))
                yield return day;
        }

        public static List<DateTime> GenerateEachDayBreakfast(DateRange range, Hotels currentHotel)
        {
            List<DateTime> fixedRangeDayList = new List<DateTime>();
            var rangeTemp = range;

            foreach (DateTime rangeIndex in EachDayWithTimeZero(rangeTemp, currentHotel))
            {
                fixedRangeDayList.Add(rangeIndex);
            }


            return fixedRangeDayList;
        }


        public static List<DateTime> GenerateEachDayRoomCharge(DateRange range, Hotels currentHotel)
        {
            var context = new ezCloudDataContext();
            
            List<DateTime> fixedRangeDayList = new List<DateTime>();
            
            if (range.Start.AddMinutes(currentHotel.TimeZoneOffset).Date != range.End.AddMinutes(currentHotel.TimeZoneOffset).Date)
            {
                foreach (DateTime rangeIndex in EachDayWithTime(range, currentHotel))
                {
                    if (rangeIndex.AddMinutes(currentHotel.TimeZoneOffset).Date != range.End.AddMinutes(currentHotel.TimeZoneOffset).Date)
                    {
                        fixedRangeDayList.Add(rangeIndex);
                    }
                }
            }
            else
            {
                fixedRangeDayList.Add(range.Start);
            }

            return fixedRangeDayList;
        }

        public static async Task CreateRoomBreakfasts(DateRange dateRange, ReservationRooms reservationRooms, UserProfile user, ezCloudDataContext context)
        {
            if (context == null)
            {
                context = new ezCloudDataContext();
            }
            List<DateTime> dayList = GenerateEachDayBreakfast(dateRange, reservationRooms.Hotels);
            foreach (DateTime day in dayList)
            {
                RoomBreakfast roomBreakfast = new RoomBreakfast();
                roomBreakfast.ReservationRooms = reservationRooms;
                roomBreakfast.HotelId = user.HotelId;
                roomBreakfast.CreatedDate = DateTime.UtcNow;
                roomBreakfast.CreatedUserId = user.UserId;
                roomBreakfast.IsBreakfast = true;
                roomBreakfast.UsedDate = day;
                roomBreakfast.UpdatedUserId = user.UserId;
                roomBreakfast.UpdatedDate = DateTime.UtcNow;
                context.RoomBreakfast.InsertOnSubmit(roomBreakfast);
            }
            context.SubmitChanges();
        }

        public static async Task CreateRoomCharges(DateRange dateRange, ReservationRooms reservationRooms, UserProfile user, ezCloudDataContext context)
        {
            if (context == null)
            {
                context = new ezCloudDataContext();
            }
            var currentHotel = reservationRooms.Hotels;
            if (currentHotel == null)
            {
                currentHotel = context.Hotels.FirstOrDefault(htl => htl.HotelId == user.HotelId);
            }
            List<DateTime> roomChargeDateList = GenerateEachDayRoomCharge(dateRange, currentHotel);
            foreach (DateTime day in roomChargeDateList)
            {
                RoomCharges roomCharge = new RoomCharges()
                {
                    ReservationRooms = reservationRooms,
                    HotelId = user.HotelId,
                    RoomId = reservationRooms.RoomId,
                    StartDate = day,
                    EndDate = day,
                    RoomTypeId = reservationRooms.RoomTypeId,
                    Amount = reservationRooms.Price,
                    RoomPriceId = reservationRooms.RoomPriceId
                };
                context.RoomCharges.InsertOnSubmit(roomCharge);
            }
            context.SubmitChanges();
        }


        public static async Task RebuildRoomBreakfasts(DateRange dateRange, ReservationRooms oldRR, UserProfile user, ezCloudDataContext context)
        {
            if (context == null)
            {
                context = new ezCloudDataContext();
            }
            List<RoomBreakfast> newRoomBreakfast = new List<RoomBreakfast>();
            List<RoomBreakfast> oldRoomBreakfast = oldRR.RoomBreakfastList.ToList();
            List<DateTime> newBreakfastDayList = GenerateEachDayBreakfast(dateRange, oldRR.Hotels);
            foreach (DateTime day in newBreakfastDayList)
            {
                var temp = oldRoomBreakfast.Where(or => or.UsedDate.Value.Date == day.Date).FirstOrDefault();
                if (temp == null)
                {
                    RoomBreakfast roomBreakfast = new RoomBreakfast();
                    roomBreakfast.ReservationRooms = oldRR;
                    roomBreakfast.HotelId = user.HotelId;
                    roomBreakfast.CreatedDate = DateTime.UtcNow;
                    roomBreakfast.CreatedUserId = user.UserId;
                    roomBreakfast.IsBreakfast = true;
                    roomBreakfast.UsedDate = day;
                    roomBreakfast.UpdatedDate = DateTime.UtcNow;
                    roomBreakfast.UpdatedUserId = user.UserId;
                    newRoomBreakfast.Add(roomBreakfast);
                }
                else
                {
                    RoomBreakfast roomBreakfast = new RoomBreakfast();
                    roomBreakfast.ReservationRoomId = temp.ReservationRoomId;
                    roomBreakfast.HotelId = temp.HotelId;
                    roomBreakfast.CreatedDate = temp.CreatedDate;
                    roomBreakfast.CreatedUserId = temp.CreatedUserId;
                    roomBreakfast.IsBreakfast = temp.IsBreakfast;
                    roomBreakfast.UsedDate = temp.UsedDate;
                    roomBreakfast.UpdatedDate = temp.UpdatedDate;
                    roomBreakfast.UpdatedUserId = temp.UpdatedUserId;
                    newRoomBreakfast.Add(roomBreakfast);
                }
            }

            if (newRoomBreakfast.Count() > 0)
            {
                context.ExecuteCommand("Delete RoomBreakfast where HotelId={0} and ReservationRoomId={1}", user.HotelId, oldRR.ReservationRoomId);
                context.RoomBreakfast.InsertAllOnSubmit(newRoomBreakfast);
            }
            context.SubmitChanges();
        }



        public static async Task RebuildRoomCharges(DateRange dateRange, ReservationRooms oldRR, UserProfile user, ezCloudDataContext context)
        {
            if (context == null)
            {
                context = new ezCloudDataContext();
            }
            List<RoomCharges> newRoomCharge = new List<RoomCharges>();
            List<RoomCharges> oldRoomCharge = oldRR.RoomChargesList.ToList();

            List<DateTime> newRoomChargeDayList = GenerateEachDayRoomCharge(dateRange, oldRR.Hotels);
            foreach (DateTime day in newRoomChargeDayList)
            {
                var temp = oldRoomCharge.Where(or => or.StartDate.Value.AddMinutes(oldRR.Hotels.TimeZoneOffset).Date == day.AddMinutes(oldRR.Hotels.TimeZoneOffset).Date).FirstOrDefault();
                if (temp == null)
                {
                    RoomCharges roomCharge = new RoomCharges()
                    {
                        ReservationRooms = oldRR,
                        HotelId = user.HotelId,
                        StartDate = day,
                        EndDate = day,
                        RoomId = oldRR.RoomId,
                        RoomTypeId = oldRR.RoomTypeId,
                        RoomPriceId = oldRR.RoomPriceId,
                        Amount = oldRR.Price
                    };
                    newRoomCharge.Add(roomCharge);
                }
                else
                {
                    RoomCharges roomCharge = new RoomCharges()
                    {
                        ReservationRooms = oldRR,
                        HotelId = user.HotelId,
                        StartDate = day,
                        EndDate = day,
                        RoomId = temp.RoomId,
                        RoomTypeId = temp.RoomTypeId,
                        RoomPriceId = temp.RoomPriceId,
                        Amount = temp.Amount
                    };
                    newRoomCharge.Add(roomCharge);
                }
            }

            if (newRoomCharge.Count() > 0)
            {
                //context.RoomCharges.DeleteAllOnSubmit(oldRoomCharge);
                context.ExecuteCommand("Delete RoomCharges where HotelId={0} and ReservationRoomId={1}", user.HotelId, oldRR.ReservationRoomId);
                context.RoomCharges.InsertAllOnSubmit(newRoomCharge);
            }
            context.SubmitChanges();
            //Elastic.IndexLastAudit(context);
        }


        public static async Task RebuildRoomChargesAndBreakfastCM(List<ReservationRooms> reservationRoomList,List<RoomCharges> roomCharges, List<RoomBreakfast> roomBreakfasts, ezCloudDataContext context)
        {
            using (context == null ? new ezCloudDataContext() : context)
            {
                
                var currentHotel = reservationRoomList[0].Hotels;
                //var completionSource = new TaskCompletionSource<bool>();
                List<RoomBreakfast> oldRoomBreakfast = roomBreakfasts;
                List<RoomCharges> oldRoomCharge = roomCharges;

                foreach (var oldRR in reservationRoomList)
                {
                    var dateRange = new DateRange(oldRR.ArrivalDate.Value, oldRR.DepartureDate.Value);
                    List<RoomCharges> newRoomCharge = new List<RoomCharges>();
                    List<DateTime> newRoomChargeDayList = GenerateEachDayRoomCharge(dateRange, oldRR.Hotels);
                    foreach (DateTime day in newRoomChargeDayList)
                    {
                        var temp = oldRoomCharge.Where(or => or.StartDate.Value.AddMinutes(oldRR.Hotels.TimeZoneOffset).Date == day.AddMinutes(oldRR.Hotels.TimeZoneOffset).Date).FirstOrDefault();
                        if (temp == null)
                        {
                            RoomCharges roomCharge = new RoomCharges()
                            {
                                ReservationRooms = oldRR,
                                HotelId = currentHotel.HotelId,
                                StartDate = day,
                                EndDate = day,
                                RoomId = oldRR.RoomId,
                                RoomTypeId = oldRR.RoomTypeId,
                                RoomPriceId = oldRR.RoomPriceId,
                                Amount = oldRR.Price
                            };
                            newRoomCharge.Add(roomCharge);
                        }
                        else
                        {
                            RoomCharges roomCharge = new RoomCharges()
                            {
                                ReservationRooms = oldRR,
                                HotelId = currentHotel.HotelId,
                                StartDate = day,
                                EndDate = day,
                                RoomId = temp.RoomId,
                                RoomTypeId = temp.RoomTypeId,
                                RoomPriceId = temp.RoomPriceId,
                                Amount = temp.Amount
                            };
                            newRoomCharge.Add(roomCharge);
                        }
                    }

                    if (newRoomCharge.Count() > 0)
                    {
                        context.ExecuteCommand("Delete RoomCharges where HotelId={0} and ReservationRoomId={1}", currentHotel.HotelId, oldRR.ReservationRoomId);
                        context.RoomCharges.InsertAllOnSubmit(newRoomCharge);
                    }
                    List<RoomBreakfast> newRoomBreakfast = new List<RoomBreakfast>();

                    List<DateTime> newBreakfastDayList = GenerateEachDayBreakfast(dateRange, currentHotel);
                    foreach (DateTime day in newBreakfastDayList)
                    {
                        var temp = oldRoomBreakfast.Where(or => or.UsedDate.Value.Date == day.Date).FirstOrDefault();
                        if (temp == null)
                        {
                            RoomBreakfast roomBreakfast = new RoomBreakfast();
                            roomBreakfast.ReservationRooms = oldRR;
                            roomBreakfast.HotelId = currentHotel.HotelId;
                            roomBreakfast.CreatedDate = DateTime.UtcNow;
                            roomBreakfast.CreatedUserId = currentHotel.HotelOwnerId;
                            roomBreakfast.IsBreakfast = true;
                            roomBreakfast.UsedDate = day;
                            roomBreakfast.UpdatedDate = DateTime.UtcNow;
                            roomBreakfast.UpdatedUserId = currentHotel.HotelOwnerId;
                            newRoomBreakfast.Add(roomBreakfast);
                        }
                        else
                        {
                            RoomBreakfast roomBreakfast = new RoomBreakfast();
                            roomBreakfast.ReservationRooms = oldRR;
                            roomBreakfast.HotelId = temp.HotelId;
                            roomBreakfast.CreatedDate = temp.CreatedDate;
                            roomBreakfast.CreatedUserId = temp.CreatedUserId;
                            roomBreakfast.IsBreakfast = temp.IsBreakfast;
                            roomBreakfast.UsedDate = temp.UsedDate;
                            roomBreakfast.UpdatedDate = temp.UpdatedDate;
                            roomBreakfast.UpdatedUserId = temp.UpdatedUserId;
                            newRoomBreakfast.Add(roomBreakfast);
                        }
                    }

                    if (newRoomBreakfast.Count() > 0)
                    {
                        context.ExecuteCommand("Delete RoomBreakfast where HotelId={0} and ReservationRoomId={1}", currentHotel.HotelId, oldRR.ReservationRoomId);
                        context.RoomBreakfast.InsertAllOnSubmit(newRoomBreakfast);
                    }
                }

                context.SubmitChanges();
            }
        }

        public static async Task RebuildAvailableRoom(ReservationRooms newRR, UserProfile user, ezCloudDataContext context,bool isRepair=false)
        {
            Hotels currentHotel;
            if (newRR.Hotels == null)
            {
                currentHotel = context.Hotels.FirstOrDefault(ht => ht.HotelId == user.HotelId);
            }
            else
            {
                currentHotel = newRR.Hotels;
            }
            if (currentHotel != null )
            {
                Elastic.IndexReservationRoom(newRR.ReservationRoomId);
                if (newRR == null || newRR.DepartureDate < DateTime.UtcNow)
                {
                    return;
                }

                var currentArrivalDate = newRR.ArrivalDate < DateTime.UtcNow ? DateTime.UtcNow : newRR.ArrivalDate;
                var arrivalDateToCompare = currentArrivalDate.Value.AddMinutes(currentHotel.TimeZoneOffset).Date.AddMinutes(-currentHotel.TimeZoneOffset);
                var departureDateToCompare = newRR.DepartureDate.Value.AddMinutes(currentHotel.TimeZoneOffset).Date.AddMinutes(-currentHotel.TimeZoneOffset);
                
                var hotelCMConfig = currentHotel.CMConfigurationsList.FirstOrDefault();
                if (hotelCMConfig != null)
                {
                    if (hotelCMConfig.IsLastRoomAvailable == true)
                    {
                        var availableRooms = Utilities.GetRoomAvailabilityMatrix(currentHotel.HotelId, arrivalDateToCompare, departureDateToCompare);
                        var cmAvailabilityMatrix = currentHotel.CMAvailabilityMatrixsList.Where(
                            av => av.CMRoomTypeMappings.RoomTypeId == newRR.RoomTypeId
                            && av.CMRoomTypeMappings.IsDeleted == false 
                            && arrivalDateToCompare <= av.MatrixDate
                            && av.MatrixDate <= departureDateToCompare);
                        if (cmAvailabilityMatrix != null && cmAvailabilityMatrix.Count() > 0)
                        {
                            foreach (var av in cmAvailabilityMatrix)
                            {
                                foreach (DataRow row in availableRooms.Rows)
                                {
                                    var date = (DateTime)row["Dates"];
                                    var total = row["CanBeSold"];
                                    var roomTypeId = (int)row["RoomTypeId"];
                                    if (av.MatrixDate.Value.Date == date.Date && roomTypeId == av.CMRoomTypeMappings.RoomTypeId && av.CMRoomTypeMappings.IsDeleted==false)
                                    {
                                        // if action does not repair: do not send to CM the end of day excepted arrivaldate equal departuredate. 
                                        if (arrivalDateToCompare.Date < departureDateToCompare.Date && av.MatrixDate.Value.Date == departureDateToCompare.Date && isRepair==false) break;

                                        av.CanBeSold = Convert.ToInt32(total);
                                        av.LastModifiedDate = DateTime.Now;
                                        av.LastModifiedUserId = user.UserId;
                                        var newCMBackgroundJob = new CMBackgroundJobs
                                        {
                                            HotelId = user.HotelId,
                                            CMRoomTypeMappingId = av.CMRoomTypeMappingId,
                                            StartDate = av.MatrixDate,
                                            EndDate = av.MatrixDate,
                                            ActionStatus = 0,
                                            ActionName = "AVAILABILITY",
                                            ActionValue = total.ToString(),
                                            CreatedDate = DateTime.UtcNow,
                                            CreatedUserId = user.UserId
                                        };
                                        context.CMBackgroundJobs.InsertOnSubmit(newCMBackgroundJob);
                                        break;
                                    }
                                }
                            }
                            context.SubmitChanges();
                            //Elastic.IndexLastAudit(context);
                            
                        }
                    }
                }
               
            }
        }
        public static void RebuildAvailableRoomOnMatrix(string action, List<ReservationRooms> newRR, Hotels currentHotel, ezCloudDataContext context)
        {
            var hotelCMConfig = currentHotel.CMConfigurationsList.FirstOrDefault();
            var totalAdjusted = 0;
            if (action=="cancel") 
            {
                //update AvailableRoom on matrix and send to STAAH
                totalAdjusted = 1;
            }
            if (action == "new")
            {
                totalAdjusted = -1;
            }
            if (currentHotel != null)
            {
                    // update avaiableRom on matrix, do not send to STAAH
                if (hotelCMConfig != null)
                {
                    if (hotelCMConfig.IsLastRoomAvailable == true)
                    {
                        foreach (var RR in newRR)
                        {
                            if (RR.DepartureDate > DateTime.UtcNow)
                            {

                                var currentArrivalDate = RR.ArrivalDate < DateTime.UtcNow ? DateTime.UtcNow : RR.ArrivalDate;
                                var arrivalDateToCompare = currentArrivalDate.Value.AddMinutes(currentHotel.TimeZoneOffset).Date.AddMinutes(-currentHotel.TimeZoneOffset);
                                var departureDateToCompare = RR.DepartureDate.Value.AddMinutes(currentHotel.TimeZoneOffset).Date.AddMinutes(-currentHotel.TimeZoneOffset);
                                var availableRooms = Utilities.GetRoomAvailabilityMatrix(currentHotel.HotelId, arrivalDateToCompare, departureDateToCompare);
                                var cmAvailabilityMatrix = currentHotel.CMAvailabilityMatrixsList.Where(
                                    av => av.CMRoomTypeMappings.RoomTypeId == RR.RoomTypeId
                                && av.CMRoomTypeMappings.IsDeleted == false
                                && arrivalDateToCompare <= av.MatrixDate
                                && av.MatrixDate <= departureDateToCompare);

                                if (cmAvailabilityMatrix != null && cmAvailabilityMatrix.Count() > 0)
                                {
                                    foreach (var av in cmAvailabilityMatrix)
                                    {
                                        foreach (DataRow row in availableRooms.Rows)
                                        {
                                            var date = (DateTime)row["Dates"];
                                            var total = row["CanBeSold"];
                                            var roomTypeId = (int)row["RoomTypeId"];
                                            if (av.MatrixDate.Value.Date == date.Date && roomTypeId == av.CMRoomTypeMappings.RoomTypeId && av.CMRoomTypeMappings.IsDeleted == false)
                                            {
                                                // if action does not repair: do not send to CM the end of day excepted arrivaldate equal departuredate. 
                                                if (arrivalDateToCompare.Date < departureDateToCompare.Date && av.MatrixDate.Value.Date == departureDateToCompare.Date) break;

                                                av.CanBeSold = Convert.ToInt32(total);
                                                av.LastModifiedDate = DateTime.Now;
                                                av.LastModifiedUserId = currentHotel.HotelOwnerId;
                                                var newCMBackgroundJob = new CMBackgroundJobs
                                                {
                                                    HotelId = currentHotel.HotelId,
                                                    CMRoomTypeMappingId = av.CMRoomTypeMappingId,
                                                    StartDate = av.MatrixDate,
                                                    EndDate = av.MatrixDate,
                                                    ActionStatus = 0,
                                                    ActionName = "AVAILABILITY",
                                                    ActionValue = total.ToString(),
                                                    CreatedDate = DateTime.UtcNow,
                                                    CreatedUserId = currentHotel.HotelOwnerId
                                                };
                                                context.CMBackgroundJobs.InsertOnSubmit(newCMBackgroundJob);
                                                break;
                                            }
                                        }
                                    }
                                    context.SubmitChanges();
                                    //Elastic.IndexLastAudit(context);
                                }
                            }
                        }
                    }

                    if (hotelCMConfig.IsLastRoomAvailable==false && action=="new")
                    {
                        // do not update on matrix if action="cancel"

                        foreach (var RR in newRR)
                        {
                            if (RR.DepartureDate > DateTime.UtcNow)
                            {
                                var currentArrivalDate = RR.ArrivalDate < DateTime.UtcNow ? DateTime.UtcNow : RR.ArrivalDate;
                                var arrivalDateToCompare = currentArrivalDate.Value.AddMinutes(currentHotel.TimeZoneOffset).Date.AddMinutes(-currentHotel.TimeZoneOffset);
                                var departureDateToCompare = RR.DepartureDate.Value.AddMinutes(currentHotel.TimeZoneOffset).Date.AddMinutes(-currentHotel.TimeZoneOffset);
                                var cmAvailabilityMatrix = currentHotel.CMAvailabilityMatrixsList.Where(
                                    av => av.CMRoomTypeMappings.RoomTypeId == RR.RoomTypeId
                                && av.CMRoomTypeMappings.IsDeleted == false
                                && arrivalDateToCompare <= av.MatrixDate
                                && av.MatrixDate < departureDateToCompare);

                                if (cmAvailabilityMatrix != null && cmAvailabilityMatrix.Count() > 0)
                                {
                                    //update on Matrix
                                    foreach (var av in cmAvailabilityMatrix)
                                    {
                                        av.CanBeSold = av.CanBeSold == null ? 0 + totalAdjusted : Convert.ToInt32(av.CanBeSold) + totalAdjusted;
                                        av.LastModifiedDate = DateTime.Now;
                                        av.LastModifiedUserId = currentHotel.HotelOwnerId;
                                    }
                                    context.SubmitChanges();
                                    //Elastic.IndexLastAudit(context);

                                }
                            }

                        }
                    }
                }   
            }

            
               
           
        }

        public async static Task CreateRoomInvoice(CalculateRoomPrice model)
        {
            var context = new ezCloudDataContext();
            var currentClientUser = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == currentClientUser.HotelId).FirstOrDefault();
            var currentReservation = context.ReservationRooms.Where(rr => rr.HotelId == currentClientUser.HotelId && rr.ReservationRoomId == model.reservationRoomId).FirstOrDefault();
            model.roomTypeId = (int)currentReservation.RoomTypeId;
            if (currentReservation.BookingStatus != "CHECKOUT" && currentReservation.BookingStatus != "CANCELLED")
            {
                var planListDateRange = await RoomPriceUtilities.CalculateRoomPrice(model);
                // Delete Old Items
                List<ReportItems> oldItems = context.ReportItems.Where(rpi => rpi.ReservationRoomId == model.reservationRoomId).ToList();
                context.ReportItems.DeleteAllOnSubmit(oldItems);

                // Create Report Items
                if (planListDateRange.planListConstantlyFormula.Count > 0)
                {
                    foreach (var formula in planListDateRange.planListConstantlyFormula)
                    {
                        ReportItems item = new ReportItems();
                        string nameTemp = "";
                        if (formula.Name == "MONTHLY_PRICE")
                        {
                            nameTemp = model.languageKeys["ROOM_MONTHLY"].ToString();
                        }
                        if (formula.Name == "WEEKLY_PRICE")
                        {
                            nameTemp = model.languageKeys["ROOM_WEEKLY"].ToString();
                        }
                        item.ReservationRoomId = model.reservationRoomId;
                        item.ItemName = nameTemp + "(" + formula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + " - " + formula.Range.End.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + ")";
                        item.ItemDescription = nameTemp + "(" + formula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + " - " + formula.Range.End.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + ")";
                        item.ItemDate = formula.Range.Start.Date.AddHours(currentHotel.TimeZoneOffset / 60);
                        item.ItemQuantity = formula.FormulaPeriod;
                        item.ItemPrice = formula.FormulaValue;
                        item.ItemTotal = formula.ValueAfter - formula.ValueBefore;
                        item.ItemType = "ROOM_PRICE_CONSTANTLY";
                        context.ReportItems.InsertOnSubmit(item);
                    }
                }

                if (planListDateRange.planListFullDayFormula.Count > 0)
                {
                    int count = planListDateRange.planListFullDayFormula.Count;

                    if (currentReservation.RoomPrices.UseHourlyPrice == true)
                    {
                        ReportItems item = new ReportItems();
                        item.ReservationRoomId = model.reservationRoomId;
                        item.ItemName = model.languageKeys["ROOM_FULL_DAY"].ToString() + "(" + planListDateRange.planListFullDayFormula[0].range.Start.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + " - " + planListDateRange.planListFullDayFormula[count - 1].range.End.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + ")";
                        item.ItemDescription = model.languageKeys["ROOM_FULL_DAY"].ToString() + "(" + planListDateRange.planListFullDayFormula[0].range.Start.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + " - " + planListDateRange.planListFullDayFormula[count - 1].range.End.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + ")";
                        item.ItemDate = planListDateRange.planListFullDayFormula[0].range.Start.AddHours(currentHotel.TimeZoneOffset / 60);
                        item.ItemQuantity = count;
                        item.ItemPrice = planListDateRange.planListFullDayFormula[0].formula.FormulaValue;
                        item.ItemTotal = (decimal)item.ItemQuantity * item.ItemPrice;
                        item.ItemType = "ROOM_PRICE_FULL_DAY";
                        context.ReportItems.InsertOnSubmit(item);
                    }
                    else
                    {
                        foreach (var formulaTemp in planListDateRange.planListFullDayFormula)
                        {
                            ReportItems item = new ReportItems();
                            item.ReservationRoomId = model.reservationRoomId;
                            item.ItemName = model.languageKeys["ROOM_FULL_DAY"].ToString();
                            item.ItemDescription = model.languageKeys["ROOM_FULL_DAY"].ToString();
                            item.ItemDate = formulaTemp.range.Start.AddHours(currentHotel.TimeZoneOffset / 60);
                            item.ItemQuantity = 1;
                            item.ItemPrice = formulaTemp.formula.FormulaValue;
                            item.ItemTotal = (decimal)item.ItemQuantity * item.ItemPrice;
                            item.ItemType = "ROOM_PRICE_FULL_DAY";
                            context.ReportItems.InsertOnSubmit(item);
                        }
                    }

                    if (planListDateRange.planListFullDayFormula[0].formula.FormulaEarlyCheckIn != null)
                    {
                        ReportItems itemEarlyCheckIn = new ReportItems();
                        itemEarlyCheckIn.ReservationRoomId = model.reservationRoomId;
                        itemEarlyCheckIn.ItemName = model.languageKeys["FULL_DAY_EARLY_CHECKIN"].ToString();
                        itemEarlyCheckIn.ItemDescription = model.languageKeys["FULL_DAY_EARLY_CHECKIN"].ToString();
                        itemEarlyCheckIn.ItemDate = planListDateRange.planListFullDayFormula[0].range.Start.AddHours(currentHotel.TimeZoneOffset / 60);
                        itemEarlyCheckIn.ItemQuantity = 1;
                        var earlyCheckIn = (decimal)planListDateRange.planListFullDayFormula[0].formula.FormulaEarlyCheckIn.Values.FirstOrDefault();
                        if (earlyCheckIn != 0)
                        {
                            itemEarlyCheckIn.ItemPrice = (decimal)planListDateRange.planListFullDayFormula[0].formula.FormulaEarlyCheckIn.Values.FirstOrDefault();
                            itemEarlyCheckIn.ItemTotal = (decimal)planListDateRange.planListFullDayFormula[0].formula.FormulaEarlyCheckIn.Values.FirstOrDefault();
                        }
                        itemEarlyCheckIn.ItemType = "FULL_DAY_EARLY_CHECKIN";
                        context.ReportItems.InsertOnSubmit(itemEarlyCheckIn);
                    }

                    if (planListDateRange.planListFullDayFormula[count - 1].formula.FormulaLateCheckOut != null)
                    {
                        ReportItems itemLateCheckOut = new ReportItems();
                        itemLateCheckOut.ReservationRoomId = model.reservationRoomId;
                        itemLateCheckOut.ItemName = model.languageKeys["FULL_DAY_LATE_CHECKOUT"].ToString();
                        itemLateCheckOut.ItemDescription = model.languageKeys["FULL_DAY_LATE_CHECKOUT"].ToString();
                        itemLateCheckOut.ItemDate = planListDateRange.planListFullDayFormula[count - 1].range.End.AddHours(currentHotel.TimeZoneOffset / 60);
                        itemLateCheckOut.ItemQuantity = 1;
                        var lateCheckOut = (decimal)planListDateRange.planListFullDayFormula[count - 1].formula.FormulaLateCheckOut.Values.FirstOrDefault();
                        if (lateCheckOut != 0)
                        {
                            itemLateCheckOut.ItemPrice = (decimal)planListDateRange.planListFullDayFormula[count - 1].formula.FormulaLateCheckOut.Values.First();
                            itemLateCheckOut.ItemTotal = (decimal)planListDateRange.planListFullDayFormula[count - 1].formula.FormulaLateCheckOut.Values.First();
                        }

                        itemLateCheckOut.ItemType = "FULL_DAY_LATE_CHECKOUT";
                        context.ReportItems.InsertOnSubmit(itemLateCheckOut);
                    }
                }

                if (planListDateRange.planListHourlyFormula != null && planListDateRange.planListHourlyFormula.finalHourlyFormula != null)
                {
                    string nameHourlyTemp = "";
                    if (planListDateRange.planListHourlyFormula.finalHourlyFormula.Name == "FULL_DAY_PRICE")
                    {
                        nameHourlyTemp = model.languageKeys["ROOM_FULL_DAY"].ToString();
                    }
                    else if (planListDateRange.planListHourlyFormula.finalHourlyFormula.Name == "DAY_NIGHT_PRICE")
                    {
                        nameHourlyTemp = model.languageKeys["ROOM_DAY_NIGHT"].ToString();
                    }
                    else
                    {
                        nameHourlyTemp = model.languageKeys["ROOM_HOURLY"].ToString();
                    }

                    ReportItems item = new ReportItems();
                    item.ReservationRoomId = model.reservationRoomId;

                    item.ItemName = nameHourlyTemp + "(" + planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + " - " + planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.End.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + ")";
                    item.ItemDescription = nameHourlyTemp + "(" + planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + " - " + planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.End.AddHours(currentHotel.TimeZoneOffset / 60).ToString("dd/MM HH:mm") + ")";
                    item.ItemDate = planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60);
                    item.ItemQuantity = 1;
                    item.ItemPrice = planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaValue;
                    item.ItemTotal = (decimal)item.ItemQuantity * item.ItemPrice;
                    item.ItemType = "ROOM_PRICE_HOURLY";
                    context.ReportItems.InsertOnSubmit(item);

                    if (planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaEarlyCheckIn != null)
                    {
                        string nameTemp = "";
                        if (planListDateRange.planListHourlyFormula.finalHourlyFormula.Name == "FULL_DAY_PRICE")
                        {
                            nameTemp = model.languageKeys["FULL_DAY_EARLY_CHECKIN"].ToString();
                        }
                        else
                        {
                            nameTemp = model.languageKeys["DAY_NIGHT_EARLY_CHECKIN"].ToString();
                        }

                        ReportItems itemEarlyCheckIn = new ReportItems();
                        itemEarlyCheckIn.ReservationRoomId = model.reservationRoomId;
                        itemEarlyCheckIn.ItemName = nameTemp;
                        itemEarlyCheckIn.ItemDescription = nameTemp;
                        itemEarlyCheckIn.ItemDate = planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60);
                        itemEarlyCheckIn.ItemQuantity = 1;
                        var earlyCheckIn = (decimal)planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaEarlyCheckIn.Values.FirstOrDefault();
                        if (earlyCheckIn != 0)
                        {
                            itemEarlyCheckIn.ItemPrice = (decimal)planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaEarlyCheckIn.Values.FirstOrDefault();
                            itemEarlyCheckIn.ItemTotal = (decimal)planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaEarlyCheckIn.Values.FirstOrDefault();
                        }

                        itemEarlyCheckIn.ItemType = "HOURLY_EARLY_CHECKIN";
                        context.ReportItems.InsertOnSubmit(itemEarlyCheckIn);
                    }

                    if (planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaLateCheckOut != null)
                    {
                        string nameTemp = "";
                        if (planListDateRange.planListHourlyFormula.finalHourlyFormula.Name == "FULL_DAY_PRICE")
                        {
                            nameTemp = model.languageKeys["FULL_DAY_LATE_CHECKOUT"].ToString();
                        }
                        else
                        {
                            nameTemp = model.languageKeys["DAY_NIGHT_LATE_CHECKOUT"].ToString();
                        }

                        ReportItems itemLateCheckOut = new ReportItems();
                        itemLateCheckOut.ReservationRoomId = model.reservationRoomId;
                        itemLateCheckOut.ItemName = nameTemp;
                        itemLateCheckOut.ItemDescription = nameTemp;
                        itemLateCheckOut.ItemDate = planListDateRange.planListHourlyFormula.finalHourlyFormula.Range.Start.AddHours(currentHotel.TimeZoneOffset / 60);
                        itemLateCheckOut.ItemQuantity = 1;
                        var earlyCheckIn = (decimal)planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaLateCheckOut.Values.FirstOrDefault();
                        if (earlyCheckIn != 0)
                        {
                            itemLateCheckOut.ItemPrice = (decimal)planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaLateCheckOut.Values.FirstOrDefault();
                            itemLateCheckOut.ItemTotal = (decimal)planListDateRange.planListHourlyFormula.finalHourlyFormula.FormulaLateCheckOut.Values.FirstOrDefault();
                        }

                        itemLateCheckOut.ItemType = "HOURLY_EARLY_CHECKIN";
                        context.ReportItems.InsertOnSubmit(itemLateCheckOut);
                    }
                }

                if (planListDateRange.extraAdults != null)
                {
                    ReportItems item = new ReportItems();
                    item.ReservationRoomId = model.reservationRoomId;
                    item.ItemName = model.languageKeys["EXTRA_ADULTS"].ToString();
                    item.ItemDescription = model.languageKeys["EXTRA_ADULTS"].ToString();
                    item.ItemDate = null;
                    item.ItemQuantity = planListDateRange.extraAdults.Extra;
                    item.ItemPrice = planListDateRange.extraAdults.DefaultPrice;
                    item.ItemTotal = planListDateRange.extraAdults.ExtraPrice;
                    item.ItemType = "EXTRA_TRAVELLER";
                    context.ReportItems.InsertOnSubmit(item);
                }

                if (planListDateRange.extraChildren != null)
                {
                    ReportItems item = new ReportItems();
                    item.ReservationRoomId = model.reservationRoomId;
                    item.ItemName = model.languageKeys["EXTRA_CHILDREN"].ToString();
                    item.ItemDescription = model.languageKeys["EXTRA_CHILDREN"].ToString();
                    item.ItemDate = null;
                    item.ItemQuantity = planListDateRange.extraChildren.Extra;
                    item.ItemPrice = planListDateRange.extraChildren.DefaultPrice;
                    item.ItemTotal = planListDateRange.extraChildren.ExtraPrice;
                    item.ItemType = "EXTRA_TRAVELLER";
                    context.ReportItems.InsertOnSubmit(item);
                }

                List<ExtraServiceItems> extraServiceItems = context.ExtraServiceItems.Where(esi => esi.HotelId == currentClientUser.HotelId).ToList();
                List<RoomExtraServices> roomExtraServices = context.RoomExtraServices.Where(rs => rs.HotelId == currentClientUser.HotelId && rs.ReservationRoomId == model.reservationRoomId).ToList();
                if (roomExtraServices.Count > 0)
                {
                    foreach (var roomES in roomExtraServices)
                    {
                        if (roomES.RoomExtraServiceName != "EXTRA_SERVICES")
                        {
                            List<RoomExtraServiceItems> roomExtraServiceItems = context.RoomExtraServiceItems.Where(rsi => rsi.HotelId == currentClientUser.HotelId && rsi.ReservationRoomId == model.reservationRoomId && rsi.RoomExtraServiceId == roomES.RoomExtraServiceId && !rsi.IsDeleted).ToList();
                            foreach (var roomESItem in roomExtraServiceItems)
                            {
                                ReportItems item = new ReportItems();
                                item.ReservationRoomId = model.reservationRoomId;
                                item.ItemName = extraServiceItems.Where(esi => esi.ExtraServiceItemId == roomESItem.ExtraServiceItemId).FirstOrDefault().ExtraServiceItemName;
                                item.ItemDescription = extraServiceItems.Where(esi => esi.ExtraServiceItemId == roomESItem.ExtraServiceItemId).FirstOrDefault().ExtraServiceItemName;
                                DateTime dateTemp = roomES.CreatedDate ?? default(DateTime);
                                item.ItemDate = dateTemp.AddHours(currentHotel.TimeZoneOffset / 60);
                                item.ItemQuantity = roomESItem.Quantity;
                                item.ItemPrice = roomESItem.Price;
                                item.ItemTotal = roomESItem.Quantity * roomESItem.Price;
                                item.ItemType = roomES.RoomExtraServiceName;
                                context.ReportItems.InsertOnSubmit(item);
                            }
                        }
                        else
                        {
                            if (!roomES.IsDeleted)
                            {
                                ReportItems item = new ReportItems();
                                item.ReservationRoomId = model.reservationRoomId;
                                item.ItemName = roomES.RoomExtraServiceDescription;
                                item.ItemDescription = roomES.RoomExtraServiceDescription;
                                DateTime dateTemp = roomES.CreatedDate ?? default(DateTime);
                                item.ItemDate = dateTemp.AddHours(currentHotel.TimeZoneOffset / 60);
                                item.ItemQuantity = roomES.Quantity;
                                item.ItemPrice = roomES.Amount;
                                item.ItemTotal = roomES.Amount* roomES.Quantity;
                                item.ItemType = roomES.RoomExtraServiceName;
                                context.ReportItems.InsertOnSubmit(item);
                            }
                        }
                    }
                }

                if (!currentReservation.Foc)
                {
                    if (currentReservation.DiscountFlat > 0 || currentReservation.DiscountPercentage > 0)
                    {
                        ReservationRooms reservationRooms = context.ReservationRooms.Where(rr => rr.HotelId == currentClientUser.HotelId && rr.ReservationRoomId == model.reservationRoomId).FirstOrDefault();
                        if (reservationRooms.DiscountFlat > 0)
                        {
                            ReportItems item = new ReportItems();
                            item.ReservationRoomId = model.reservationRoomId;
                            item.ItemName = model.languageKeys["DISCOUNT_MONEY_OFF"].ToString();
                            item.ItemDescription = model.languageKeys["DISCOUNT_MONEY_OFF"].ToString();
                            //DateTime dateTemp = payment.CreatedDate ?? default(DateTime);
                            item.ItemDate = null;
                            item.ItemQuantity = 1;
                            item.ItemPrice = reservationRooms.DiscountFlat;
                            item.ItemTotal = -(decimal?)item.ItemQuantity * item.ItemPrice;
                            item.ItemType = "DISCOUNT";
                            context.ReportItems.InsertOnSubmit(item);
                        }
                        if (reservationRooms.DiscountPercentage > 0)
                        {
                            ReportItems item = new ReportItems();
                            item.ReservationRoomId = model.reservationRoomId;
                            item.ItemName = model.languageKeys["DISCOUNT_PERCENT_OFF"].ToString() + " (" + model.DiscountPercentage.ToString() + "%)"; ;
                            item.ItemDescription = model.languageKeys["DISCOUNT_PERCENT_OFF"].ToString() + " (" + model.DiscountPercentage.ToString() + "%)";
                            item.ItemDate = null;
                            item.ItemQuantity = 1;
                            item.ItemPrice = planListDateRange.discountPercentageAmount;
                            item.ItemTotal = -(decimal?)item.ItemQuantity * item.ItemPrice;
                            item.ItemType = "DISCOUNT";
                            context.ReportItems.InsertOnSubmit(item);
                        }
                    }
                }
                else
                {
                    ReportItems item = new ReportItems();
                    item.ReservationRoomId = model.reservationRoomId;
                    item.ItemName = model.languageKeys["FREE"].ToString();
                    item.ItemDescription = model.languageKeys["FREE"].ToString();
                    item.ItemDate = null;
                    item.ItemQuantity = null;
                    item.ItemPrice = 0;
                    item.ItemTotal = planListDateRange.focAmount;
                    item.ItemType = "DISCOUNT";
                    context.ReportItems.InsertOnSubmit(item);
                }

                context.SubmitChanges();
                Common.Elastic.IndexLastAudit(context);
            }
            // }

            //return Ok();
        }
   }
}